package com.itchen.school.common.jdkext.lambda;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.itchen.school.common.exception.SysException;
import com.itchen.school.common.jdkext.Function1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

public class LambdaUtils {

    public LambdaUtils() {}

    private static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        } else {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);

            try {
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(object);
                oos.flush();
            } catch (IOException var3) {
                throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), var3);
            }

            return baos.toByteArray();
        }
    }

    public static <T> String getFieldName(Function1<T, ?> func, boolean camelTransform) {
        if (!func.getClass().isSynthetic()) {
            throw new SysException("该方法仅能传入 lambda 表达式产生的合成类");
        } else {
            try {
                ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(serialize(func))) {
                    protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                        Class<?> clazz = super.resolveClass(objectStreamClass);
                        return clazz == SerializedLambda.class ? SerializedLambda.class : clazz;
                    }
                };

                String toUpperCase;
                label58: {
                    String var6;
                    label57: {
                        try {
                            SerializedLambda desc = (SerializedLambda)objIn.readObject();
                            String name = desc.getImplMethodName();
                            if (camelTransform) {
                                toUpperCase = StringUtils.camelToUnderline(name).toUpperCase();
                                if (toUpperCase.startsWith("GET_")) {
                                    toUpperCase = toUpperCase.replaceFirst("GET_", "");
                                }

                                if (toUpperCase.startsWith("SET_")) {
                                    toUpperCase = toUpperCase.replaceFirst("SET_", "");
                                }

                                var6 = toUpperCase;
                                break label57;
                            }

                            if (!name.startsWith("get") && !name.startsWith("set")) {
                                toUpperCase = name;
                                break label58;
                            }

                            toUpperCase = name.substring(3);
                        } catch (Throwable var8) {
                            try {
                                objIn.close();
                            } catch (Throwable var7) {
                                var8.addSuppressed(var7);
                            }

                            throw var8;
                        }

                        objIn.close();
                        return toUpperCase;
                    }

                    objIn.close();
                    return var6;
                }

                objIn.close();
                return toUpperCase;
            } catch (IOException | ClassNotFoundException var9) {
                throw new SysException("This is impossible to happen", var9);
            }
        }
    }

    public static <T> String getFieldName(Function1<T, ?> func) {
        return getFieldName(func, true);
    }

    public static Class<?> getRawType(Type type) {
        if (type instanceof Class) {
            return (Class)type;
        } else if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType)type;
            Type rawType = parameterizedType.getRawType();
            return (Class)rawType;
        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType)type).getGenericComponentType();
            return Array.newInstance(getRawType(componentType), 0).getClass();
        } else if (type instanceof TypeVariable) {
            return Object.class;
        } else if (type instanceof WildcardType) {
            return getRawType(((WildcardType)type).getUpperBounds()[0]);
        } else {
            String className = type == null ? "null" : type.getClass().getName();
            throw new IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <" + type + "> is of type " + className);
        }
    }

    public static <R> Function1<R, ?>[] function1s(Function1<R, ?>... funs) {
        return funs;
    }

}
